package org.example.study4;

// 只给一个线程加锁，也会出现线程安全问题
// 虽然 increase() 方法通过 synchronized 保证原子性，但 increase1() 方法未同步，
// 导致两个线程同时操作共享变量 count 时仍存在数据竞争，最终结果小于预期值（10 万）
public class Demo_403 {
    public static void main(String[] args) throws InterruptedException {
        // 初始化累加对象
        Counter403 counter = new Counter403(); // 创建 Counter403 实例

        // 创建两个线程分别调用不同方法对共享变量累加
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 50000; i++) {
                counter.increase(); // 调用同步方法
            }
        });

        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 50000; i++) {
                counter.increase1(); // 调用非同步方法
            }
        });

        // 启动线程
        t1.start(); // 启动线程1（执行 increase()）
        t2.start(); // 启动线程2（执行 increase1()）

        // 等待线程执行完成
        t1.join();  // 主线程等待线程1结束
        t2.join();  // 主线程等待线程2结束

        // 输出结果（通常小于 10 万）
        System.out.println("count = " + counter.count);
    }
}


class Counter403 {
    public int count = 0; // 共享变量

    /**
     * 同步累加方法
     */
    public synchronized void increase() { // 使用对象锁（this）
        count++; // 原子操作（在同步保护下）
    }

    /**
     * 非同步累加方法
     */
    public void increase1() { // 无同步机制，无锁
        count++; // 非原子操作，存在线程安全问题
    }
}

//运行： count = 73214  // 实际值随机，因线程调度而异

/*锁对象不一致：
increase() 使用 synchronized (this)（隐式对象锁），但 increase1() 无锁。
两个方法对 count 的修改没有统一锁保护，导致线程不安全。

increase1() 的线程不安全
increase1() 中的 count++ 是非原子操作（读→改→写）。
若线程1在 increase() 中执行 count++（同步），线程2在 increase1() 中同时执行 count++（非同步），可能发生以下情况：

初始值：count = 0
线程1（increase()）：读取 count=0 → 计算 0+1=1 → 写入 count=1
线程2（increase1()）：读取 count=0 → 计算 0+1=1 → 写入 count=1
最终 count 仅增加 1 次，而非预期的 2 次。
*/

/*总结：
* 线程获取锁：
1.如果只有一个线程A,那么直接可以获取锁，没有锁竞争
2.线程A和线程B共同抢一把锁的时候（如以上代码的线程t1和线程t2），存在锁竞争，谁先拿到就先执行自己的逻辑，另外一个线程阻塞等待，行到持有锁的线程释放锁之后，再参与锁竞争
3.线程A与线程B竞争的不是同一把锁/他们之间没有竞争关系
*/